package org.axed.user.client;

/**
 * An interval consisting of two AxedPointers. 
 * Other than the range this is not integrated into the document, 
 * and thus does not automatically adapt to document changes like the range.
 */
public class AxedInterval {
	public AxedPointer p1;
	public AxedPointer p2;

	private AxedArea axed;

	/**
	 * Constructor.
	 */
	public AxedInterval(AxedArea axed) {
		this.axed = axed;
		p1 = new AxedPointer(axed);
		p2 = new AxedPointer(axed);
	}

	/**
	 * Returns a short debug string.
	 */
	public String getDebugText() {
		return p1.getDebugText() + "-" + p2.getDebugText();
	}


	/**
	 * Expands this interval to reach from a line start to a line end.
	 * (used e.g. in Visual Line in vimish mode)
	 */
	public void expandToLines() {
		if (p1.compare(p2) <= 0) {
			p1.moveLineStart(false);
			p2.moveLineEnd(false);
		} else {
			p1.moveLineEnd(false);
			p2.moveLineStart(false);
		}
	}

	/**
	 * Returns true when p1 == p2
	 */
	public boolean isZero() {
		return p1.equals(p2);
	}

	/**
	 * Returns true when this interval only stratches over one line.
	 */
	public boolean isOneLined() {
		return p1.line == p2.line;
	}

	/**
	 * exchanges p1 with p2 if p2 is before the p1.
	 */
	public void normalize() {
		if (p1.line == p2.line) {
			if (p1.col > p2.col) {
				int b = p1.col;
				p1.col = p2.col;
				p2.col = b;
			}
			return;
		}
		if (p1.line > p2.line) {
			int b = p1.line;
			p1.line = p2.line;
			p2.line = b;
			b = p1.col;
			p1.col = p2.col;
			p2.col = p1.col;
		}
	}

	/**
	 * Set this interval to be equal to another interval.
	 */
	public void set(AxedInterval p) {
		p1.set(p.p1);
		p2.set(p.p2);
	}

	/**
	 * Sets both pointers to outside of the document.
	 */
	public void invalidize() {
		p1.invalidize();	
		p2.invalidize();	
	}

	/**
	 * Set this interval by to two pointers.
	 */
	public void set(AxedPointer p1, AxedPointer p2) {
		this.p1.set(p1);
		this.p2.set(p2);
	}

	/**
	 * Set this interval by ints
	 */
	public void set(int line1, int col1, int line2, int col2) {
		p1.set(line1, col1);
		p2.set(line2, col2);
	}


	/**
	 * Sets the interval over all of the document.
	 */
	public void setAll() {
		p1.movePos1();
		p2.moveEof();
	}

	/**
	 * Sets the interval over one line.
	 *
	 * @param newline  if true include the newline
	 */
	public void setLine(int line, boolean newline) {
		if (!newline) {
			p1.line = p2.line = line;
			p1.col  = 0;
			p2.col  = axed.getLineLength(line);
			return;
		}
		if (line == axed.getLineCount() - 1) {
			// if its the last line include the newline of the line before instead.
			if (line == 0) {
				// except its line 0;
				p1.line = 0;
				p1.col = 0;
				p2.line = 0;
				p2.col = axed.getLineLength(0);
				return;
			}
			p1.line = line - 1;
			p1.col = axed.getLineLength(line - 1);
			p2.line = line;
			p2.col = axed.getLineLength(line);
		} else {
			p1.line = line;
			p1.col = 0;
			p2.line = line + 1;
			p2.col = 0;
		}
	}

	/**
	 * Sets the interval over several lines.
	 *
	 * @param newline  if true include the last newline
	 */
	public void setLines(int line1, int line2, boolean newline) {
		if (!newline) {
			p1.line = line1;
			p2.line = line2;
			p1.col  = 0;
			p2.col  = axed.getLineLength(line2);
			return;
		}
		if (line2 == axed.getLineCount() - 1) {
			// if it ends at the last line include the newline of the line before instead.
			if (line1 == 0) {
				// except its line 0;
				p1.line = 0;
				p1.col = 0;
				p2.line = line2;
				p2.col = axed.getLineLength(line2);
				return;
			}
			p1.line = line1 - 1;
			p1.col = axed.getLineLength(line1 - 1);
			p2.line = line2;
			p2.col = axed.getLineLength(line2);
		} else {
			p1.line = line1;
			p1.col = 0;
			p2.line = line2 + 1;
			p2.col = 0;
		}
	}
}

